from django.utils import timezone  # django转换UTC时间为本地时间
from kubernetes.client.rest import ApiException
from kubernetes import client
from systemd.models import registryInfo


class OprationDeploymentApi():
    '''操作deployment'''

    def __init__(self, port=None, tag=None, namespace=None, deployment_name=None):
        self.port = port
        self.tag = tag
        self.namespace = namespace
        self.deployment_name = deployment_name
        from kubernetes import config
        config.load_kube_config(config_file="./kube_conf/local.conf")
        self.coreApi_v1 = client.CoreV1Api()
        self.extensions_v1beta1 = client.AppsV1Api()

    def get_deployment_api(self):
        '''获取deployment列表'''

        try:
            deployment_res = self.extensions_v1beta1.list_namespaced_deployment(namespace=self.namespace,
                                                                                async_req=True).get()
        except ApiException as e:
            return {'code': 500, 'msg': 'deployment列表获取失败,%s' % str(e)}
        else:
            results = []
            for deployment in deployment_res.items:
                deployments = {}
                deployments['name'] = deployment.metadata.name
                deployments['replicas'] = f'{deployment.status.ready_replicas}/{deployment.spec.replicas}'
                deployments['read_replicas'] = deployment.status.ready_replicas
                for conditions in deployment.status.conditions:
                    deployments['status'] = conditions.status.lower()
                    deployments['message'] = conditions.message
                    deployments['update_time'] = timezone.localtime(conditions.last_update_time).strftime(
                        "%Y-%m-%d %H:%M:%S")
                for containers_spec in deployment.spec.template.spec.containers:
                    if containers_spec.ports is None:
                        deployments['port'] = 'None'
                    else:
                        deployments['port'] = containers_spec.ports[0].container_port
                results.append(deployments)
            return results

    def get_deployment_name_api(self):
        '''获取namespace对应所有deployment名称'''

        try:
            deployment_res = self.extensions_v1beta1.list_namespaced_deployment(namespace=self.namespace,
                                                                                async_req=True).get()
        except ApiException as e:
            return {'code': 500, 'msg': 'deployment列表获取失败'}
        else:
            # 此处仅获取deployment名称
            results = [deployment.metadata.name for deployment in deployment_res.items]
            return results

    def delete_deployment_api(self):
        '''删除deployment，将整个关联的容器组全部删除'''

        from .service_core import OprationServiceApi
        from .ingress_core import OprationIngressApi
        try:
            Body = client.V1DeleteOptions(
                propagation_policy='Foreground',
                grace_period_seconds=3
            )
            self.extensions_v1beta1.delete_namespaced_deployment(name=self.deployment_name, namespace=self.namespace,
                                                                 body=Body, async_req=True).get()
        except ApiException as e:
            return {'code': 500, 'msg': f'deployment {self.deployment_name} 删除失败'}
        else:
            # 删除关系的service和ingress服务
            service_obj = OprationServiceApi(namespace=self.namespace, service_name=self.deployment_name)
            ingress_obj = OprationIngressApi(namespace=self.namespace, ingress_name=self.deployment_name)
            service_list = service_obj.get_service_name_api()
            ingress_list = ingress_obj.get_ingress_name_api()
            if self.deployment_name in service_list:
                service_obj.delete_service_api()
            if self.deployment_name in ingress_list:
                ingress_obj.delete_ingress_api()
            return {'msg': f'deployment {self.deployment_name} 删除成功'}

    def create_deployment_obj_api(self, replicas=1):
        '''创建deployment对象'''

        registry = registryInfo.objects.filter(env=self.namespace).values('registry', 'namespace').first()

        container = client.V1Container(
            name=self.deployment_name,
            image_pull_policy='Always',
            image=f"{registry.get('registry')}/{registry.get('namespace')}/{self.deployment_name}:{self.tag}",
            ports=[client.V1ContainerPort(container_port=int(self.port))],
            volume_mounts=[client.V1VolumeMount(name="log", mount_path="/var/logs"),
                           client.V1VolumeMount(name="localtime", mount_path="/etc/localtime")],
            env=[client.V1EnvVar(name="envs", value=self.namespace),
                 client.V1EnvVar(name="TZ", value="Asia/Shanghai"),
                 ],
            # resources=client.V1ResourceRequirements(
            #     limits={"cpu": "500m", "memory": "1Gi"},
            #     requests={"cpu": "500m", "memory": "512Mi"},
            # )
        )
        template = client.V1PodTemplateSpec(
            metadata=client.V1ObjectMeta(labels={"name": self.deployment_name}),
            spec=client.V1PodSpec(containers=[container],
                                  volumes=[client.V1Volume(name="log", host_path=client.V1HostPathVolumeSource(
                                      path=f"/var/log/apps/{self.namespace}")),
                                           client.V1Volume(name="localtime", host_path=client.V1HostPathVolumeSource(
                                               path="/etc/localtime"))])
        )
        spec = client.ExtensionsV1beta1DeploymentSpec(
            replicas=replicas,
            template=template,
            selector=client.V1LabelSelector(match_labels={"name": self.deployment_name}),
            strategy=client.ExtensionsV1beta1DeploymentStrategy(
                type='RollingUpdate',
                rolling_update=client.ExtensionsV1beta1RollingUpdateDeployment(max_surge=1, max_unavailable=0)
            ),
            min_ready_seconds=3
        )
        deployment = client.ExtensionsV1beta1Deployment(
            api_version="extensions/v1beta1",
            kind="Deployment",
            metadata=client.V1ObjectMeta(name=self.deployment_name, namespace=self.namespace),
            spec=spec)
        return deployment

    def create_deployment_api(self):
        '''创建deployment'''

        try:
            self.extensions_v1beta1.create_namespaced_deployment(
                namespace=self.namespace, body=self.create_deployment_obj_api(), async_req=True
            )
        except ApiException as e:
            return {'code': 500, 'msg': f'deployment {self.deployment_name} 创建失败,{str(e)}.'}
        # else:
        #     print(deployment_res.status)
        # return {'msg':f'deployment {self.deployment_name} 创建成功!'}

    def update_deployment_api(self):
        '''更新deployoment'''

        registry = registryInfo.objects.filter(env=self.namespace).values('registry', 'namespace').first()
        image = f"{registry.get('registry')}/{registry.get('namespace')}/{self.deployment_name}:{self.tag}"
        self.create_deployment_obj_api().spec.template.spec.containers[0].image = image
        try:
            self.extensions_v1beta1.patch_namespaced_deployment(
                namespace=self.namespace, name=self.deployment_name, body=self.create_deployment_obj_api(),
                async_req=True).get()
        except ApiException as e:
            return {'code': 500, 'msg': f'deployment {self.deployment_name} 更新失败，{str(e)}'}
        # else:
        #     print(deployment_res.status)
        # return {'msg':f'deployment {self.deployment_name} 更新成功!'}
